from typing import TYPE_CHECKING
from dataclasses import dataclass

from puzzle.tile import TileSet

if TYPE_CHECKING:
    from puzzle.board import Board
    from puzzle.tile import TileType_t

@dataclass
class PrecheckResult:
    n_tiles: int
    dead_tiles: list[TileSet]
    
    def has_dead_tile(self) -> bool:
        return len(self.dead_tiles) != 0

def _is_dead(board: "Board", tileset: TileSet) -> bool:
    all_tiles = TileSet()
    for td in tileset:
        for t in board.get_adjacent_tiles_by_td(td):
            all_tiles.add(t)
    
    visited_type: list["TileType_t"] = []
    for td in all_tiles.difference(tileset):
        if td.tile.type in visited_type:
            return False
        visited_type.append(td.tile.type)
    return True

def precheck_1t(board: "Board") -> PrecheckResult:
    dead: list[TileSet] = []
    for td in board.tiles_flatten:
        if td.tile.is_blank: continue
        
        tileset = TileSet(td)
        if _is_dead(board, tileset):
            dead.append(tileset)
    
    return PrecheckResult(1, dead)
    
def precheck_2t(board: "Board") -> PrecheckResult:
    tilesets: list[TileSet] = []
    for td1 in board.tiles_flatten:
        if td1.tile.is_blank: continue
        
        for td2 in board.get_adjacent_tiles_by_td(td1):
            if td2.tile.is_blank: continue
            tilesets.append(TileSet(td1, td2))

    ts_unique = []
    for ts in tilesets:
        if ts not in ts_unique:
            ts_unique.append(ts)
    
    dead: list[TileSet] = []
    for ts in ts_unique:
        if _is_dead(board, ts):
            dead.append(ts)
    return PrecheckResult(2, dead)

def precheck_3t(board: "Board") -> PrecheckResult:
    tilesets: list[TileSet] = []
    for td1 in board.tiles_flatten:
        if td1.tile.is_blank: continue
        
        for td2 in board.get_adjacent_tiles_by_td(td1):
            if td2.tile.is_blank: continue
            
            for td3 in board.get_adjacent_tiles_by_td(td2):
                if td3.tile.is_blank or td3 == td1: continue
                tilesets.append(TileSet(td1, td2, td3))

    ts_unique = []
    for ts in tilesets:
        if ts not in ts_unique:
            ts_unique.append(ts)
    
    dead: list[TileSet] = []
    for ts in ts_unique:
        if _is_dead(board, ts):
            dead.append(ts)
    return PrecheckResult(3, dead)